home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 19.zip / BS1 part 19 / AmigaLibDisk 154.adf / PrintSpool / Print.c < prev    next >
C/C++ Source or Header  |  1987-06-15  |  19KB  |  576 lines

  1.  
  2. /* Print.c    V1.0.0    27-Mar-88    ) Frangois Gagnon */
  3.  
  4. /*
  5.    Copyright ) 1988  Frangois Gagnon,  All Rights Reserved.
  6.  
  7.    The author does not make any warranty expressed or implied,
  8.    or assumes any liability or responsiblity for the use of
  9.    this software.
  10.  
  11.    Permission is hereby granted to copy, reproduce, redistribute
  12.    or otherwise use this software as long as it is for non-profit.
  13.    This notice and the above copyright notice must remain intact
  14.    and appear on all copies.
  15.  
  16.    Permission is also granted to correct any problems with this
  17.    software, but modifications and improvements are reserved by
  18.    the author.
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <time.h>
  24.  
  25. #include <exec/memory.h>
  26. #include <exec/ports.h>
  27. #include <exec/nodes.h>
  28. #include <intuition/preferences.h>
  29. #include <libraries/dos.h>
  30. #include <libraries/dosextens.h>
  31.  
  32. #include "stdefs.h"
  33. #include "Print_Spool.h"
  34.  
  35. /* Declarations of status messages */
  36. local    char    FIND[] = "\nPrint: Unable to find Spool port.\n\n";
  37. local    char    PROT[] = "\nPrint: Mismatched protocol versions.\n\n";
  38. local    char    PORT[] = "\nPrint: Unable to create Print port.\n\n";
  39. local    char    DATA[] = "\nPrint: Unable to allocate memory.\n\n";
  40. local    char    EXEC[] = "\nPrint: Unknown or ambiguous command = %s.\n\n";
  41. local    char    LOCK[] = "\nPrint: File not found = %s.\n\n";
  42. local    char    TYPE[] = "\nPrint: Wrong file type = %s.\n\n";
  43. local    char    SIZE[] = "\nPrint: File name too long = %s%s.\n\n";
  44.  
  45. /* Definition for Execution */
  46. local    struct    Inform        *Print_Data;
  47. local    struct    MsgPort     *Spool_Port, *Print_Port;
  48. local    struct    FileInfoBlock    *Print_Info;
  49.  
  50. local    File    *Print_List = NULL, *Print_Last = NULL;
  51. local    int     Print_File = PS_Insert;
  52. local    int     Print_Opts = (Opts_Headers | Opts_Numbers);
  53. local    int     Print_Flag = 0;
  54. local    int     Print_Copy = 1;
  55.  
  56. #define Options( Mask, Opts) (Print_Opts = (Print_Opts & ~Mask) + Opts)
  57. ^L
  58. /*****************************/
  59. /* Define Available Commands */
  60. /*****************************/
  61.  
  62. /* Add option commands */
  63. #define    PS_CPI10     30
  64. #define PS_CPI12    31
  65. #define PS_CPI17     32
  66. #define PS_LPI6        33
  67. #define PS_LPI8        34
  68. #define PS_NARROW    35
  69. #define PS_WIDE     36
  70. #define PS_SHORT    37
  71. #define PS_LONG     38
  72.  
  73. #define PS_HEADER    40
  74. #define PS_NUMBER    41
  75. #define PS_KEEP     42
  76. #define PS_DELETE    43
  77. #define PS_DRAFT    44
  78. #define PS_LETTER    45
  79.  
  80. /* Define the data structure */
  81. #define Print_Size    26
  82. #define Print_Used     7
  83. struct    Print_Type    { char Name[Print_Used];
  84.               byte Code;
  85.             };
  86.  
  87. local    struct    Print_Type    Print_Exec[Print_Size] = {
  88.   { "CANCEL", PS_Cancel }, { "CHANGE", PS_Change }, { "CPI10",  PS_CPI10  },
  89.   { "CPI12",  PS_CPI12  }, { "CPI17",  PS_CPI17  }, { "DELETE", PS_DELETE },
  90.   { "DRAFT",  PS_DRAFT  }, { "FINISH", PS_Finish }, { "FREEZE", PS_Freeze },
  91.   { "HEADER", PS_HEADER }, { "INSERT", PS_Insert }, { "KEEP",   PS_KEEP   },
  92.   { "LETTER", PS_LETTER }, { "LONG",   PS_LONG   }, { "LPI6",   PS_LPI6   },
  93.   { "LPI8",   PS_LPI8   }, { "NARROW", PS_NARROW }, { "NUMBER", PS_NUMBER },
  94.   { "REMOVE", PS_Remove }, { "REPORT", PS_Report }, { "RESET",  PS_Resets },
  95.   { "RESUME", PS_Resume }, { "RETURN", PS_Return }, { "SHORT",  PS_SHORT  },
  96.   { "UPDATE", PS_Update }, { "WIDE",   PS_WIDE   }};
  97. ^L
  98. /********************************/
  99. /* Search Allowing Abbreviatoin */
  100. /********************************/
  101.  
  102. local    int    Find_Command( Name)
  103. /*********************************/
  104. register char    Name[];
  105.  
  106. { register int    Length, Result;
  107.   auto       int  Test,   Next;
  108.   extern   int    strncmp();
  109.  
  110.   for (Length = 0; Name[Length] != NUL; ++Length)
  111.     Name[Length] = toupper( Name[Length]);
  112.  
  113.   Next = 1; Result = -1;
  114.   do /* The name table must be sorted */
  115.   { Test = Next;
  116.     if (++Result == Print_Size) { Next = -1; break; }
  117.     Next = strncmp( Name, Print_Exec[Result].Name, Length);
  118.   }
  119.   while (Test > 0);
  120.  
  121.   if ((Test != 0) || (Next == 0)) return 0;
  122.   return Print_Exec[Result - 1].Code;
  123. }
  124. ^L
  125. /******************************/
  126. /* Initialization of Defaults */
  127. /******************************/
  128.  
  129. #define INTUITIONNAME        "intuition.library"
  130. public    struct IntuitionBase    *IntuitionBase;
  131.  
  132. local    void    Default_Values()
  133. /******************************/
  134.  
  135. { auto     struct Preferences    PrefBuffer;
  136.   auto     int            Temp;
  137.   extern struct IntuitionBase  *OpenLibrary();
  138.   extern struct Preferences    *GetPrefs();
  139.  
  140.   /* Fetch the information from the system */
  141.   IntuitionBase = OpenLibrary( INTUITIONNAME, 0L);
  142.   if (IntuitionBase == NULL) return;
  143.   GetPrefs( &PrefBuffer, (long) sizeof( struct Preferences));
  144.   CloseLibrary( IntuitionBase);
  145.  
  146.   /* Extract the information from the structure */
  147.   if      (PrefBuffer.PrintPitch == ELITE) Print_Opts |= Line_12;
  148.   else if (PrefBuffer.PrintPitch == FINE)  Print_Opts |= Line_17;
  149.  
  150.   Temp = (PrefBuffer.PrintSpacing == EIGHT_LPI ? 8 : 6);
  151.   if (PrefBuffer.PrintQuality == LETTER)    Print_Flag |= Flag_Quality;
  152.   if (PrefBuffer.PrintSpacing == EIGHT_LPI) Print_Opts |= Page_8;
  153.   if (PrefBuffer.PaperSize    == W_TRACTOR) Print_Opts |= Line_13;
  154.   if (PrefBuffer.PaperLength / Temp == 11)  Print_Opts |= Page_11;
  155. }
  156.  
  157.  
  158. /****************************/
  159. /* Printing Utility Routine */
  160. /****************************/
  161.  
  162. local    char    Value[3][3] = { "10", "12", "17" };
  163.  
  164. local    void    Show_File( Info_File)
  165. /***********************************/
  166. register File    *Info_File;
  167.  
  168. { printf( "%3s%4s%4s%4s%3c%c%c%c%6d %6ld  %s\n",
  169.     Value[Info_File->File_Opts & Line_Density],
  170.     (Info_File->File_Opts & Line_Formats ? "13" :   "8"),
  171.     (Info_File->File_Opts & Page_Density ?  "8" :   "6"),
  172.     (Info_File->File_Opts & Page_Formats ? "11" : "8.5"),
  173.     (Info_File->File_Opts & Opts_Headers ?  'T' :   'F'),
  174.     (Info_File->File_Opts & Opts_Numbers ?  'T' :   'F'),
  175.     (Info_File->File_Flag & Flag_Quality ?  'L' :   'D'),
  176.     (Info_File->File_Flag & Flag_Deleted ?  'D' :   'K'),
  177.     Info_File->File_Copy, Info_File->File_Size, Info_File->File_Name);
  178. }
  179. ^L
  180. /*********************************/
  181. /* General Communication Routine */
  182. /*********************************/
  183.  
  184. local    int    Request_Action( Action)
  185. /*************************************/
  186. int    Action;
  187.  
  188. { extern struct MsgPort *FindPort();
  189.   extern struct    Inform    *GetMsg();
  190.  
  191.   /* Prepare the message for sending */
  192.   Print_Data->Packet.mn_Node.ln_Type = NT_MESSAGE;
  193.   Print_Data->Packet.mn_ReplyPort    = Print_Port;
  194.   Print_Data->Number             = PROTOCOL;
  195.   Print_Data->Action             = Action;
  196.  
  197.   /* Send the request message across  */
  198.   /* Making sure the port still exist */
  199.   Forbid();
  200.   if ((Spool_Port = FindPort( SPOOLNAME)) == NULL)
  201.   { Permit(); fprintf( stderr, FIND); return TRUE; }
  202.   PutMsg( Spool_Port, Print_Data);
  203.   Permit();
  204.  
  205.   /* Receive the result message */
  206.   do    WaitPort( Print_Port);
  207.   while ((Print_Data = GetMsg( Print_Port)) == NULL);
  208.  
  209.   /* Check the protocol version */
  210.   if (Print_Data->Number != PROTOCOL)
  211.   { fprintf( stderr, PROT); return TRUE; }
  212.   return FALSE;
  213. }
  214. ^L
  215. /*************************************/
  216. /* Request the status of the Spooler */
  217. /*************************************/
  218.  
  219. local    char    *State[] =
  220.     { "\nSpool: Waiting for a file to print.\n",
  221.       "\nSpool: Waiting for a change of paper.\n",
  222.       "\nSpool: Waiting to access the printer.\n",
  223.       "\nSpool: Printing a requested file.\n",
  224.       "\nSpool: Printing but will pause after the file.\n",
  225.       "\nSpool: Pausing between two files.\n",
  226.       "\nSpool: Pausing in the middle of a file.\n"
  227.     };
  228.  
  229. local    void    Request_Report()
  230. /******************************/
  231.  
  232. { register File *File_List, *File_Next;
  233.   register byte  Prog_Info;
  234.  
  235.   /* Request the wanted operation */
  236.   if (Request_Action( PS_Report)) return;
  237.  
  238.   /* Display the status information */
  239.   printf( State[Prog_Info = Print_Data->Detail.Status.Prog_State]);
  240.   if (Print_Data->Detail.Status.Flag_State)
  241.     printf( "Spool: Set to terminate its execution.\n");
  242.   if (Print_Data->Detail.Status.Opts_State & Flag_Partial)
  243.     printf( "Spool: Partial list of files, unable to allocate memory.\n");
  244.   if ((Prog_Info == Exec_State) || (Prog_Info == File_State) ||
  245.       (Prog_Info == Stop_State) )
  246.   { printf( "Spool: Printing %ld chars ... %ld lines ... %ld pages.\n",
  247.         Print_Data->Detail.Status.Char_Print,
  248.         Print_Data->Detail.Status.Line_Print,
  249.         Print_Data->Detail.Status.Page_Print);
  250.   }
  251.  
  252.   /* Display the contents of the print queue */
  253.   if ((File_List = Print_Data->Detail.Status.File_Print) != NULL)
  254.   { printf( "\ncpi ipl lpi ipp  hnqd  copy   size  report\n");
  255.     do
  256.     { File_List = (File_Next = File_List)->File_Next;
  257.       Show_File( File_Next);
  258.       FreeMem( File_Next, (long) sizeof( File));
  259.     }
  260.     while (File_List != NULL);
  261.   }
  262.   putchar( '\n');
  263. }
  264. ^L
  265. /*************************************/
  266. /* Request the removal of some files */
  267. /*************************************/
  268.  
  269. local    void    Request_Remove( Name)
  270. /***********************************/
  271. char    Name[];
  272.  
  273. { register File *Temp_File, *Temp_Next;
  274.   strncpy( Print_Data->Detail.Remove, Name, Name_Size);
  275.   if (Request_Action( PS_Remove)) return;
  276.  
  277.   if ((Temp_File = Print_Data->Detail.Insert) != NULL)
  278.   { printf( "\ncpi ipl lpi ipp  hnqd  copy   size  remove\n");
  279.     do
  280.     { Temp_File = (Temp_Next = Temp_File)->File_Next;
  281.       Show_File( Temp_Next);
  282.       FreeMem( Temp_Next, (long) sizeof( File));
  283.     }
  284.     while (Temp_File != NULL);
  285.   }
  286.   putchar( '\n');
  287. }
  288. ^L
  289. /**************************************/
  290. /* Perform the specified file request */
  291. /**************************************/
  292.  
  293. local    void    Perform()
  294. /***********************/
  295.  
  296. { if (Print_List != NULL)
  297.   { /* Execute the operation */
  298.     if (Print_File == PS_Insert) Print_Data->Detail.Insert = Print_List;
  299.     if (Print_File == PS_Update) Print_Data->Detail.Update = Print_List;
  300.     Print_Last->File_Next = NULL;
  301.     if (Request_Action( Print_File))
  302.     { do
  303.       { Print_List = (Print_Last = Print_List)->File_Next;
  304.     FreeMem( Print_Last, (long) sizeof( File));
  305.       }
  306.       while (Print_List != NULL);
  307.       return;
  308.     }
  309.  
  310.     if (Print_File == PS_Insert) Print_List = NULL;
  311.     if (Print_File == PS_Update)
  312.     { printf( "\ndone   cpi ipl lpi ipp  hnqd  copy   size  update\n");
  313.       do
  314.       { Print_List = (Print_Last = Print_List)->File_Next;
  315.     printf( "%s",
  316.       (Print_Last->File_Flag & Flag_Updated ?  "TRUE   " : "FALSE  "));
  317.     Show_File( Print_Last);
  318.     FreeMem( Print_Last, (long) sizeof( File));
  319.       }
  320.       while (Print_List != NULL);
  321.       putchar( '\n');
  322. } } }
  323. ^L
  324. /*********************************/
  325. /* File Search Utililty Routines */
  326. /*********************************/
  327.  
  328. local     int    File_Match( Name, Data)
  329. /*************************************/
  330. register char    *Name, *Data;
  331.  
  332. { auto       char *Save_Name[10],
  333.         *Save_Data[10];
  334.   register int     Save;
  335.  
  336.   if ((*Data == NUL) || (*Name == NUL)) return FALSE;
  337.   Save = -1;
  338.  
  339.   while ((*Data != NUL) || (*Name != NUL))
  340.   { if (*Data == '*')
  341.     { if (*++Data == NUL) return TRUE;
  342.       if ( ++Save ==  10) return FALSE;
  343.       Save_Name[Save] = Name;
  344.       Save_Data[Save] = Data;
  345.       continue;
  346.     }
  347.     if (   ((*Data == '?') && (*Name != NUL))
  348.     || (toupper(*Data) == toupper(*Name)))
  349.     { ++Data; ++Name; continue; }
  350.  
  351.     if (*Name == NUL) --Save;
  352.     if ( Save <    0) return FALSE;
  353.     Name = ++Save_Name[Save];
  354.     Data =   Save_Data[Save];
  355.   }
  356.   return TRUE;
  357. }
  358. ^L
  359. local    int    File_Parent( File_Name, File_Path, File_Size, File_Info)
  360. /**********************************************************************/
  361. char            *File_Name, *File_Path;
  362. int             File_Size;
  363. struct    FileInfoBlock    *File_Info;
  364.  
  365. { extern   struct FileLock *Lock(),    *ParentDir();
  366.   auto       struct FileLock *File_Lock,    *File_Next;
  367.   register int            File_Save,     File_Loop;
  368.  
  369.   if ((File_Lock = Lock( File_Name, SHARED_LOCK)) == NULL) return 0;
  370.   File_Path[File_Loop = File_Size - 1] = NUL;
  371.   do
  372.   { if (!Examine( File_Lock, File_Info))
  373.     { UnLock( File_Lock); return 0; }
  374.  
  375.     File_Save = strlen( File_Info->fib_FileName) + 1;
  376.     if ((File_Loop < File_Save) || (File_Loop < 4))
  377.     { UnLock( File_Lock); return -1; }
  378.     if (File_Save == 1)
  379.      strcpy( &File_Path[File_Loop - (File_Save = 4)], "RAM");
  380.     else strcpy( &File_Path[File_Loop - File_Save], File_Info->fib_FileName);
  381.  
  382.     File_Next = ParentDir( File_Lock); UnLock( File_Lock);
  383.     File_Path[File_Loop - 1] = (File_Next == NULL ? ':' : '/');
  384.     File_Lock = File_Next; File_Loop -= File_Save;
  385.   }
  386.   while (File_Lock != NULL);
  387.  
  388.   if (File_Loop != 0) strcpy( File_Path, &File_Path[File_Loop]);
  389.   return (File_Size - File_Loop);
  390. }
  391. ^L
  392. /**********************************/
  393. /* Specific File Handling Routine */
  394. /**********************************/
  395.  
  396. local    int    File_Insert()
  397. /***************************/
  398.  
  399. { extern   void   *AllocMem();
  400.   extern   char   *ctime();
  401.   register File   *Temp_File;
  402.   auto       char   *Temp_Date;
  403.   auto       time_t  Temp_Time;
  404.  
  405.   Temp_File = AllocMem( (long) sizeof(File), MEMF_PUBLIC);
  406.   if (Temp_File == NULL) { fprintf( stderr, DATA); return TRUE; }
  407.  
  408.   Temp_Time = Print_Info->fib_Date.ds_Days   * 86400
  409.         + Print_Info->fib_Date.ds_Minute * 60
  410.         + Print_Info->fib_Date.ds_Tick   / TICKS_PER_SECOND;
  411.   Temp_Date = ctime( &Temp_Time);
  412.   memcpy( Temp_File->File_Date, &Temp_Date[4], Date_Size);
  413.  
  414.   Temp_File->File_Opts = Print_Opts;
  415.   Temp_File->File_Flag = Print_Flag;
  416.   Temp_File->File_Copy = Print_Copy;
  417.   Temp_File->File_Size = Print_Info->fib_Size;
  418.  
  419.   if (Print_List == NULL) Print_List        = Temp_File;
  420.   else              Print_Last->File_Next = Temp_File;
  421.   Print_Last = Temp_File;
  422.   return FALSE;
  423. }
  424. ^L
  425. local    void    File_Search( Name)
  426. /********************************/
  427. char    *Name;
  428.  
  429. { extern char         *strchr(), *strrchr();
  430.   extern struct FileLock *Lock();
  431.   auto     struct FileLock *File_Lock;
  432.   auto     int          File_Size;
  433.   auto     char         *File_Name, *File_Char;
  434.   auto     char          File_Path[Name_Size];
  435.  
  436.   if ((strchr( Name, '*') == NULL) && (strchr( Name, '?') == NULL))
  437.   { /* Take care of simple file name */
  438.     File_Size = File_Parent( Name, File_Path, Name_Size, Print_Info);
  439.     if (File_Size <= 0)
  440.     { if (File_Size == 0) fprintf( stderr, LOCK, Name);
  441.       else          fprintf( stderr, SIZE, Name, "");
  442.       return;
  443.     }
  444.     File_Path[File_Size - 2] = NUL;
  445.     if ((File_Lock = Lock( File_Path, SHARED_LOCK)) == NULL)
  446.     { fprintf( stderr, LOCK, Name); return; }
  447.  
  448.     if (!Examine( File_Lock, Print_Info))
  449.       fprintf( stderr, LOCK, Name);
  450.     else if (Print_Info->fib_DirEntryType >= 0)
  451.       fprintf( stderr, TYPE, Print_Info->fib_FileName);
  452.     else if (!File_Insert())
  453.       strcpy( Print_Last->File_Name, File_Path);
  454.   }
  455.   else
  456.   { /* Extract the directory part */
  457.     if (((File_Name = strrchr( Name, '/')) == NULL) &&
  458.         ((File_Name = strchr(  Name, ':')) == NULL) )
  459.          File_Name = Name;
  460.     else memcpy( File_Path, Name, ++File_Name - Name);
  461.     File_Path[File_Name - Name] = NUL;
  462.  
  463.     /* Initialize the search */
  464.     File_Size = File_Parent( File_Path, File_Path, Name_Size, Print_Info);
  465.     if (File_Size <= 0)
  466.     { if (File_Size == 0) fprintf( stderr, LOCK, Name);
  467.       else          fprintf( stderr, SIZE, Name, "");
  468.       return;
  469.     }
  470.     if ((File_Lock = Lock( File_Path, SHARED_LOCK)) == NULL)
  471.     { fprintf( stderr, LOCK, File_Path); return; }
  472. ^L
  473.     if (!Examine( File_Lock, Print_Info))
  474.       fprintf( stderr, LOCK, File_Path);
  475.     else if (Print_Info->fib_DirEntryType < 0)
  476.       fprintf( stderr, TYPE, Print_Info->fib_FileName);
  477.     else
  478.     { /* Search for the matching files */
  479.       while (ExNext( File_Lock, Print_Info))
  480.       { if ((Print_Info->fib_DirEntryType < 0)             &&
  481.         File_Match( Print_Info->fib_FileName, File_Name) )
  482.     { if (File_Size + strlen( Print_Info->fib_FileName) > Name_Size)
  483.         fprintf( stderr, SIZE, File_Path, Print_Info->fib_FileName);
  484.       else if (!File_Insert())
  485.       { strcpy( Print_Last->File_Name, File_Path);
  486.         strcpy( &Print_Last->File_Name[File_Size - 1],
  487.             Print_Info->fib_FileName);
  488.   } } } } }
  489.   UnLock( File_Lock);
  490. }
  491. ^L
  492. /************************/
  493. /* Execute the Commands */
  494. /************************/
  495.  
  496. local    void    Exec_Action( Exec)
  497. /********************************/
  498. char    Exec[];
  499.  
  500. { extern int atoi();
  501.   auto     int Code;
  502.  
  503.   if (isdigit( *Exec)) Print_Copy = atoi( Exec);
  504.   else switch( Code = Find_Command( Exec))
  505.   { /* Take care of the options */
  506.     case PS_CPI10   : Options( Line_Density, Line_10);        break;
  507.     case PS_CPI12   : Options( Line_Density, Line_12);        break;
  508.     case PS_CPI17   : Options( Line_Density, Line_17);        break;
  509.     case PS_LPI6    : Options( Page_Density, Page_6);        break;
  510.     case PS_LPI8    : Options( Page_Density, Page_8);        break;
  511.     case PS_NARROW  : Options( Line_Formats, Line_8);        break;
  512.     case PS_WIDE    : Options( Line_Formats, Line_13);        break;
  513.     case PS_SHORT   : Options( Page_Formats, Page_85);        break;
  514.     case PS_LONG    : Options( Page_Formats, Page_11);        break;
  515.     case PS_HEADER  : Print_Opts ^=  Opts_Headers;        break;
  516.     case PS_NUMBER  : Print_Opts ^=  Opts_Numbers;        break;
  517.     case PS_KEEP    : Print_Flag &= ~Flag_Deleted;        break;
  518.     case PS_DELETE  : Print_Flag |=  Flag_Deleted;        break;
  519.     case PS_DRAFT   : Print_Flag &= ~Flag_Quality;        break;
  520.     case PS_LETTER  : Print_Flag |=  Flag_Quality;        break;
  521.  
  522.     /* Take care of the actions */
  523.     case PS_Insert  : case PS_Update  : case PS_Remove :
  524.       if (Print_File != Code) Perform();
  525.       Print_File = Code;                    break;
  526.  
  527.     case PS_Report  : Perform(); Request_Report();        break;
  528.  
  529.     case PS_Return  : case PS_Change  : case PS_Freeze :
  530.     case PS_Finish  : case PS_Resets  : case PS_Cancel :
  531.     case PS_Resume  : Perform(); Request_Action( Code);        break;
  532.  
  533.     /* Take care of unknown commands */
  534.     default        : fprintf( stderr, EXEC, Exec);        break;
  535. } }
  536. ^L
  537. /*****************************/
  538. /* This is the Print program */
  539. /*****************************/
  540.  
  541. public    void    main( argc, argv)
  542. /*******************************/
  543. int     argc;
  544. char    *argv[];
  545.  
  546. { extern struct MsgPort *CreatePort();
  547.   extern void        *AllocMem();
  548.  
  549.   printf( "Print  V1.0  27-Mar-88  ) Frangois Gagnon\n");
  550.  
  551.   /* Allocate Initial Structure */
  552.   Print_Port = CreatePort( NULL, 0L);
  553.   if (Print_Port == NULL) { fprintf( stderr, PORT); exit(1); }
  554.   Print_Data = AllocMem( (long) sizeof(struct Inform), MEMF_PUBLIC);
  555.   if (Print_Data == NULL) { fprintf( stderr, DATA); goto Abort1; }
  556.   Print_Info = AllocMem( (long) sizeof(struct FileInfoBlock), MEMF_PUBLIC);
  557.   if (Print_Info == NULL) { fprintf( stderr, DATA); goto Abort2; }
  558.   Default_Values();
  559.  
  560.   /* Analyze the given arguments */
  561.   if (argc == 1) Request_Report();
  562.   else
  563.   { while (++argv, --argc)
  564.     { if      ((*argv)[0] ==       '-') Exec_Action( &(*argv)[1]);
  565.       else if (Print_File == PS_Remove) Request_Remove( *argv);
  566.       else                File_Search( *argv);
  567.     }
  568.     if (Print_List != NULL) Perform();
  569.   }
  570.  
  571.   /* Deallocate Initial Structure */
  572.   Abort3: FreeMem( Print_Info, (long) sizeof(struct FileInfoBlock));
  573.   Abort2: FreeMem( Print_Data, (long) sizeof(struct Inform));
  574.   Abort1: DeletePort( Print_Port);
  575. }
  576.